package org.openagauss.resolver;

import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MavenDependencyAnalyzer {
    private static final Pattern DEPENDENCY_PATTERN = Pattern.compile(
        "\\[INFO\\] ([^:]+):([^:]+):([^:]*):([^:]+):([^:]+)");
    private static final Pattern ANSI_ESCAPE = Pattern.compile("\u001B\\[[;\\d]*m");
    private static final Pattern MODULE_PATTERN = Pattern.compile(
        "\\[INFO\\] --- maven-dependency-plugin:.*:tree.* @ ([^ ]+) ---");
    private static final Pattern DEPENDENCY_TREE_PREFIX = Pattern.compile("^\\s*([|\\\\\\s+\\-]+)?");

    // 需要跳过的内部组件前缀
    private static final Set<String> INTERNAL_COMPONENTS = new HashSet<>();

    {
        INTERNAL_COMPONENTS.add("org.opengauss");
        INTERNAL_COMPONENTS.add("org.huawei");
        INTERNAL_COMPONENTS.add("com.example");
    }

    // 存储所有依赖信息
    private static final Map<String, Map<String, Set<String>>> dependencyMap = new HashMap<>();
    // 存储版本冲突信息
    private static final Map<String, Map<String, Set<String>>> versionConflicts = new HashMap<>();
    // 当前处理的模块名
    private static String currentModule = "root";

    public static void main(String[] args) {
        File projectDir = new File(System.getProperty("user.dir"));
        String targetName = "Third_Party_Open_Source_Software_List.yaml";
        String conflictReport = "Dependency_Conflicts_Report.yaml";
        if (args.length > 0) {
            projectDir = new File(args[0]);
            targetName = args.length > 1 ? args[1] : targetName;
            conflictReport = targetName.replace(".yaml", "") + "_" + conflictReport;
        }
        try {
            System.out.println("项目目录: " + projectDir.getAbsolutePath());
            // 1. 执行 mvn dependency:tree 并直接解析输出
            executeAndAnalyzeMavenDependencies(projectDir);
            // 2. 生成主YAML文件
            generateMainYamlFile(targetName);
            // 3. 生成冲突报告
            generateConflictReport(conflictReport);
            System.out.println("成功生成文件:");
            System.out.println(" - 主依赖文件: " + targetName);
            System.out.println(" - 冲突报告: " + conflictReport);
        } catch (Exception e) {
            System.err.println("错误: " + e.getMessage());
            e.printStackTrace();
            System.exit(1);
        }
    }

    private static void executeAndAnalyzeMavenDependencies(File projectDir) throws IOException, InterruptedException {
        System.out.println("执行并分析Maven依赖...");
        ProcessBuilder processBuilder = new ProcessBuilder();
        // 强制更新依赖并直接输出
        String command = "mvn dependency:tree -DoutputType=text -U";
        if (System.getProperty("os.name").toLowerCase().contains("win")) {
            processBuilder.command("cmd.exe", "/c", command);
        } else {
            processBuilder.command("sh", "-c", command);
        }
        processBuilder.directory(projectDir);
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();
        // 实时解析Maven输出
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String rawLine;
            while ((rawLine = reader.readLine()) != null) {
                String line = removeAnsiEscape(rawLine);
                // 输出到控制台
                System.out.println("[MAVEN] " + line);
                // 解析依赖行
                parseDependencyLine(line);
                // 检测错误
                if (line.contains("Could not transfer artifact") || line.contains(
                    "Failed to read artifact descriptor")) {
                    System.err.println("警告: 检测到依赖问题: " + line);
                }
            }
        }
        int exitCode = process.waitFor();
        if (exitCode != 0) {
            System.err.println("Maven命令执行失败，退出码: " + exitCode);
            // 即使失败，也尝试使用已解析的数据
            if (dependencyMap.isEmpty()) {
                throw new RuntimeException("未解析到任何依赖信息");
            }
        }
        System.out.println("依赖分析完成");
        System.out.println("解析到依赖项: " + dependencyMap.size());
        System.out.println("发现版本冲突: " + versionConflicts.size());
    }

    private static void parseDependencyLine(String line) {
        // 检查模块切换
        Matcher moduleMatcher = MODULE_PATTERN.matcher(line);
        if (moduleMatcher.find()) {
            currentModule = moduleMatcher.group(1);
            System.out.println("切换到模块: " + currentModule);
            return;
        }

        // 跳过非依赖行
        if (!line.startsWith("[INFO]") || !line.contains(":")) {
            return;
        }

        // 彻底清理行首的依赖树标记和空格
        String cleanedLine = line.replaceFirst("^\\[INFO\\]\\s*", "");
        cleanedLine = DEPENDENCY_TREE_PREFIX.matcher(cleanedLine).replaceAll("");
        cleanedLine = cleanedLine.trim();

        // 处理空行或无效行
        if (cleanedLine.isEmpty()) {
            return;
        }

        // 使用改进的正则表达式匹配标准Maven依赖格式
        Matcher matcher = Pattern.compile(
            "([^:]+):([^:]+):(?:[^:]*:)?([^:]+):([^:]+)"
        ).matcher(cleanedLine);

        if (matcher.find()) {
            String groupId = matcher.group(1).trim();
            String artifactId = matcher.group(2).trim();
            String version = matcher.group(3).trim();
            String scope = matcher.group(4).trim();

            // 额外验证
            if (groupId.isEmpty() || artifactId.isEmpty() || version.isEmpty()) {
                System.out.println("警告: 缺少必要的依赖信息: " + cleanedLine);
                return;
            }

            // 跳过内部组件
            if (isInternalComponent(groupId)) {
                System.out.printf("跳过内部依赖: %s:%s:%s (scope: %s)%n",
                    groupId, artifactId, version, scope);
                return;
            }

            // 跳过测试和provided范围的依赖
            if ("test".equals(scope) || "provided".equals(scope)) {
                System.out.printf("跳过依赖: %s:%s (scope: %s)%n",
                    groupId, artifactId, scope);
                return;
            }

            // 清理版本号
            version = cleanVersion(version);

            // 添加到依赖映射
            String dependencyKey = groupId + ":" + artifactId;
            dependencyMap
                .computeIfAbsent(dependencyKey, k -> new HashMap<>())
                .computeIfAbsent(version, k -> new HashSet<>())
                .add(currentModule);

            // 检查版本冲突
            checkForVersionConflict(dependencyKey, version, currentModule);
        } else {
            // 尝试备用解析方式
            parseAlternativeDependencyFormat(cleanedLine);
        }
    }

    /**
     * 处理备用依赖格式（如无scope的情况）
     */
    private static void parseAlternativeDependencyFormat(String line) {
        // 匹配格式: groupId:artifactId:version
        Matcher alternativeMatcher = Pattern.compile(
            "([^:]+):([^:]+):([^:]+)"
        ).matcher(line);

        if (alternativeMatcher.find()) {
            String groupId = alternativeMatcher.group(1).trim();
            String artifactId = alternativeMatcher.group(2).trim();
            String version = alternativeMatcher.group(3).trim();

            // 假设scope为compile
            String scope = "compile";

            // 跳过内部组件
            if (isInternalComponent(groupId)) {
                System.out.printf("跳过内部依赖: %s:%s:%s (scope: %s)%n",
                    groupId, artifactId, version, scope);
                return;
            }

            // 清理版本号
            version = cleanVersion(version);

            // 继续处理...
            System.out.println("使用备用格式解析: " + groupId + ":" + artifactId + ":" + version);

            // 添加到依赖映射
            String dependencyKey = groupId + ":" + artifactId;
            dependencyMap
                .computeIfAbsent(dependencyKey, k -> new HashMap<>())
                .computeIfAbsent(version, k -> new HashSet<>())
                .add(currentModule);

            // 检查版本冲突
            checkForVersionConflict(dependencyKey, version, currentModule);
        }
    }

    /**
     * 清理版本号中的异常内容
     */
    private static String cleanVersion(String version) {
        // 移除可能的异常内容，如"is present in the local repository..."
        Matcher versionMatcher = Pattern.compile("^([^\\s,]+)").matcher(version);
        if (versionMatcher.find()) {
            return versionMatcher.group(1);
        }
        return version;
    }

    private static void checkForVersionConflict(String dependencyKey, String version, String module) {
        Map<String, Set<String>> versions = dependencyMap.get(dependencyKey);
        if (versions.size() > 1) {
            // 记录冲突详情
            versionConflicts.put(dependencyKey, new HashMap<>(versions));
            System.out.printf("发现版本冲突: %s%n", dependencyKey);
            versions.forEach((v, modules) -> System.out.printf(" - 版本 %s 在模块: %s%n", v, modules));
        }
    }

    private static void generateMainYamlFile(String targetName) throws IOException {
        System.out.println("生成主YAML文件...");
        Map<String, Map<String, Object>> yamlMap = new LinkedHashMap<>();
        // 统计artifactId频率
        Map<String, Integer> artifactCount = new HashMap<>();
        for (String key : dependencyMap.keySet()) {
            String artifactId = key.split(":")[1];
            artifactCount.put(artifactId, artifactCount.getOrDefault(artifactId, 0) + 1);
        }
        // 构建主YAML结构
        for (Map.Entry<String, Map<String, Set<String>>> entry : dependencyMap.entrySet()) {
            String dependencyKey = entry.getKey();
            String[] parts = dependencyKey.split(":");
            String groupId = parts[0];
            String artifactId = parts[1];
            // 选择使用频率最高的版本
            String selectedVersion = selectPrimaryVersion(entry.getValue());
            // 确定YAML键名
            String mapKey = artifactId;
            if (artifactCount.getOrDefault(artifactId, 0) > 1) {
                mapKey = groupId + ":" + artifactId;
            }
            // 创建条目 - 确保键名不包含特殊字符
            Map<String, Object> dependencyInfo = new LinkedHashMap<>();
            dependencyInfo.put("groupId", groupId);
            dependencyInfo.put("artifactId", artifactId);
            dependencyInfo.put("version", selectedVersion);
            dependencyInfo.put("url", generateDependencyUrl(groupId, artifactId, selectedVersion));
            yamlMap.put(mapKey, dependencyInfo);
        }
        // 输出YAML
        DumperOptions options = new DumperOptions();
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        options.setIndent(2);
        options.setWidth(200);
        Yaml yaml = new Yaml(options);
        try (FileWriter writer = new FileWriter(targetName)) {
            yaml.dump(yamlMap, writer);
        }
        System.out.println("主YAML文件生成完成，条目数量: " + yamlMap.size());
    }

    private static void generateConflictReport(String conflictReport) throws IOException {
        if (versionConflicts.isEmpty()) {
            System.out.println("未发现版本冲突，跳过冲突报告生成");
            return;
        }
        System.out.println("生成冲突报告...");
        Map<String, Map<String, Object>> conflictMap = new LinkedHashMap<>();
        for (Map.Entry<String, Map<String, Set<String>>> entry : versionConflicts.entrySet()) {
            String dependencyKey = entry.getKey();
            String[] parts = dependencyKey.split(":");
            String groupId = parts[0];
            String artifactId = parts[1];
            // 创建冲突条目
            Map<String, Object> conflictInfo = new LinkedHashMap<>();
            conflictInfo.put("groupId", groupId);
            conflictInfo.put("artifactId", artifactId);
            // 添加所有版本信息
            List<Map<String, Object>> versionsList = new ArrayList<>();
            entry.getValue().forEach((version, modules) -> {
                Map<String, Object> versionInfo = new LinkedHashMap<>();
                versionInfo.put("version", version);
                versionInfo.put("modules", new ArrayList<>(modules));
                versionInfo.put("url", generateDependencyUrl(groupId, artifactId, version));
                versionsList.add(versionInfo);
            });
            conflictInfo.put("versions", versionsList);
            conflictMap.put(dependencyKey, conflictInfo);
        }
        // 输出YAML
        DumperOptions options = new DumperOptions();
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        options.setIndent(2);
        options.setWidth(200);
        Yaml yaml = new Yaml(options);
        try (FileWriter writer = new FileWriter(conflictReport)) {
            yaml.dump(conflictMap, writer);
        }
        System.out.println("冲突报告生成完成，冲突项数量: " + conflictMap.size());
    }

    private static String selectPrimaryVersion(Map<String, Set<String>> versions) {
        // 选择使用模块最多的版本
        return versions.entrySet()
            .stream()
            .max(Comparator.comparingInt(entry -> entry.getValue().size()))
            .map(Map.Entry::getKey)
            .orElse(versions.keySet().iterator().next());
    }

    private static boolean isInternalComponent(String groupId) {
        return INTERNAL_COMPONENTS.stream().anyMatch(groupId::startsWith);
    }

    private static String generateDependencyUrl(String groupId, String artifactId, String version) {
        if ("javax.servlet-api".equals(artifactId)) {
            return "https://github.com/javaee/servlet-spec";
        } else if ("hutool-all".equals(artifactId)) {
            return "https://github.com/looly/hutool";
        }
        return "https://mvnrepository.com/artifact/" + groupId + "/" + artifactId + "/" + version;
    }

    private static String removeAnsiEscape(String line) {
        return ANSI_ESCAPE.matcher(line).replaceAll("");
    }
}
